#!/usr/bin/env python2

import platform
import errno
import re
import os
import string
import time

from utils import Exp, _dmsg, _dwarn, _exec_pipe, _str2dict, _file_read, _file_write
from disk_tool import DiskTool
from disk.Iface import DISK_Iface


# struct ext4_super_block offset = 1024; ext4_super_block.s_reserved offset = 588;
VALID_DATA_OFFSET = 1024 + 588
# sizeof(ext4_super_block.s_reserved) = 109
VALID_DATA_LEN = 109 + 1024
DISK_INFO_OFFSET = 4096
FILE_BLOCK_LEN = 4096

class Normal(DISK_Iface):
    def get_disk_pool(self, dev):
        buf = _file_read(dev, VALID_DATA_OFFSET, VALID_DATA_LEN)
        d = _str2dict(buf, ';', '=')
        return d['pool']

    def disk_load_valid(self, dev, clusteruuid, hostname):
        buf = _file_read(dev, VALID_DATA_OFFSET, VALID_DATA_LEN)
        d = _str2dict(buf, ';', '=')
        if 'cluster' in d and 'node' in d:
            if d['cluster'] == clusteruuid and d['node'] == hostname:
                return d

    def disk_info_valid(self, dev, buff):
        valid = _file_read(dev, DISK_INFO_OFFSET, len(buff))
        return valid == buff

    def disk_read(self, dev, offset, size):
        return _file_read(dev, offset, size)

    def disk_write(self, dev, buff, offset):
        return _file_write(dev, buff, offset)

    def get_disk_info(self, dev):
        return self.disktool.get_dev_info(dev)

    def __get_new_disk(self, used_disk):
        new_disk = []
        all_devs = self.disktool.get_all_devs()
        for dev in all_devs:
            used = False
            for item in used_disk:
                if dev in used_disk[item].keys():
                    used = True
                for disk in used_disk[item]:
                    if dev in used_disk[item][disk]:
                        used = True
            if not used:
                new_disk.append(dev)
                if '__newdev__' not in used_disk:
                    used_disk['__newdev__'] = {}
                    used_disk['__newdev__'][dev] = self.disk.get_disk_real(dev)
        return new_disk

    def get_new_disk(self, used_disk):
        return self.__get_new_disk(used_disk)

    def get_new_info(self, dev):
        return self.get_disk_info(dev)

    def show_new_disk(self, dev, dev_info):
        return self.show_disk_info(dev, dev_info)

    def get_all_disk(self, used_disk):
        return self.__get_new_disk(used_disk)

    def show_disk_info(self, dev, dev_info):
        if dev_info['media_type'] == dev_info['type']:
            media_type = dev_info['media_type']
        else:
            media_type = dev_info['media_type'] + "(" + dev_info['type'] + ")"
        info = ""
        if dev_info['mount'] is not None:
            info += " mount:" + dev_info['mount']
        if dev_info['label'] is not None and dev_info['label'] != '':
            info += " label:" + dev_info['label']
        return "  %-6s %-6s %-6s %-9s %s" %(dev, media_type, dev_info['interface'], dev_info['size'], info)

    def get_disk_speed(self, dev):
        return self.disktool.get_dev_speed(dev)

    def get_disk_rotation(self, dev):
        return self.disktool.get_dev_rotation(dev)

    def set_disk_label(self, dev, label):
        return self.disktool.set_dev_label(dev, 'lich-meta')

    def set_disk_clusteruuid(self, dev, clusteruuid):
        buff = _file_read(dev, VALID_DATA_OFFSET, VALID_DATA_LEN)
        m = re.match('cluster=(\w+);node=\w+;', buff)
        if m:
            if m.group(1) == clusteruuid:
                return
            buff = buff.replace(m.group(1), clusteruuid)
            _file_write(dev, buff, VALID_DATA_OFFSET)

    def set_disk_nodename(self, dev, nodename):
        buff = _file_read(dev, VALID_DATA_OFFSET, VALID_DATA_LEN)
        m = re.match('cluster=\w+;node=(\w+);', buff)
        if m:
            if m.group(1) == hostname:
                return
            buff = buff.replace(m.group(1), hostname)
            _file_write(dev, buff, VALID_DATA_OFFSET)

    def disk_add_superblock(self, dev, disk_num, pool, cache, clusteruuid, hostname):
        superblock = 'cluster=%s;node=%s;type=new;disk=%s;pool=%s;cache=%s;cached=0;\0' % (clusteruuid, hostname, disk_num, pool, cache)
        _file_write(dev, superblock, VALID_DATA_OFFSET)

    def disk_del_superblock(self, dev):
        buff = '\0' * FILE_BLOCK_LEN
        _file_write(dev, buff)
